--[[
This module provides data storage and access for the data representing
each drop and the corresponding loot distribution.
It contains data by Auction (drop + bids + winner) within a Raid
Auctions are numbered starting at 1 for the first auction within a
particular raid, and increasing sequentially.  Care must be taken to
ensure that this sequence is shared across any observer that may take
over the position of loot master, as having this auction number
used by multiple raiders for different loot auctions will corrupt
the data store and probably cause data to be lost.

TODO:
]]--
local LastAuctionNumber = 0
local ActiveRaid = nil
local ActiveRaidName = nil
local ActiveAuction = nil
local ActiveAuctionNumber = 0
SNFAuctions = { }

SNFAuctionChecksums = { } -- not saved right now, see if I can get this into the Auctions data.

--[[ LCOAL FUNCTIONS ]]--
local function ValidRaid(what)
	if not ActiveRaid then
		if (what ~= "silent") then
			SNFDEBUG(0, "Attempt to "..(what or "").." when no raid is started.  Use /snfdkp raid start")
		end
		return false
	end
	return true
end

local function ValidAuction(what)
	if not ValidRaid(what) then return end

	if not ActiveAuction then
		if (what ~= "silent") then
			SNFDEBUG(0, "Attempt to "..(what or "").." when no auction is started.  Looter must /ra [item] link to start an auction")
		end
		return false
	end
	return true
end

local function ValidAuctionNum(number)
	if not ValidRaid("checking auction num "..(number or "nil")) then return end

	if number == 0 or not ActiveRaid[number] then
		SNFDEBUG(1, "Invalid auction number "..(number or "nil"))
		return false
	end
	return true
end

local function ValidAuctionA(aa)
	if not ValidRaid("checking auction") then return end

	if not aa then
		SNFDEBUG(1, "Invalid auction ")
		return false
	end
	return true
end


local function ClearAuction()
	ActiveAuction = nil
end

local function EndAuction(aa, name, loot, level)
	if not ValidAuctionA(aa) then return end

--	SNFPRINT(2,"Ending auction: ", aa)

--	SNFPRINT(2, "Auction in store: ", ActiveAuction[ActiveAuctionNumber])

	aa["winner"] = name
	SNF_ClearAuctionChecksum(ActiveRaidName)
	SNFLoot:AddPlayerLoot(name, level, ActiveRaidName, loot)
	-- clear active auction if this closed it
	if aa == ActiveAuction then ActiveAuction = nil end
end

local function ListBidsForRaid(RaidAuctionList)
	for auctionnum, adata in pairs(RaidAuctionList) do
		if (adata) then
			SNFDEBUG(0, "  Auction #"..(auctionnum or "nil")..": "..(adata["AuctionItem"] or "nil").." Winner: "..(adata["winner"] or "Open"))
			if not adata["BidList"] then
				SNFDEBUG(0, "  No recorded bids,")
			else
				local test = false
				for bidder, idata in pairs(adata["BidList"]) do
					local ttl = SNFLoot:GetLootCount(bidder, idata["level"])
					local ttlthisraid = SNFLoot:GetLootCount(bidder, idata["level"], ActiveRaidName)
					SNFDEBUG(0, "    Bid: "..bidder.." for "..idata["level"].." ttl: "..(ttl or "0")..", this raid: "..(ttlthisraid or "0"))
					test = true
				end
				if not test then
					SNFPRINT(2, "adata['BidList']", adata["BidList"])
				end
			end
		end
	end
end

local function NextAuctionNumber()
	--TODO - this should proabbly scan for the last number, not just start again at 1 if nil
	if not LastAuctionNumber then LastAuctionNumber = 0 end
	LastAuctionNumber = LastAuctionNumber + 1
	ActiveAuction = ActiveRaid[LastAuctionNumber]
end

local function GetLastAuctionNum(RaidID)
	if not SNFAuctions or not SNFAuctions[RaidID] then
		return 0
	end
	return #(SNFAuctions[RaidID])
end

--[[ VARIABLE ACCESS FUNCTIONS ]]--

function SNFGetLastAuctionNumber()
	return LastAuctionNumber
end

function SNFSetLastAuctionNumber(a)
	LastAuctionNumber = a
end

function SNFGetAuctionData(raidid)

	if raidid and SNFAuctions[raidid] then
		return SNFAuctions[raidid]
	end
	return { }
end

--[[ GLOBAL FUNCTIONS ]]--
function SNFCheckLootAgainstBids(name, loot)

	if not ValidAuction("silent") then return end
	if not ActiveAuction then
		SNFDEBUG(1, "No active auction, but passed the valid check.. hrm")
	end

	local BidList = ActiveAuction["BidList"]
	local BidItem = ActiveAuction["AuctionItem"]

	itemid = SNFGetItemID(loot)
	if BidItem and loot and itemid == SNFGetItemID(BidItem) then
		SNFDEBUG(2,"CheckLootAgainstBids found a match!")
		for bidder, data in pairs(BidList) do
			SNFDEBUG(3, "CheckLootAgainstBids checking: "..bidder..","..data["level"].." against "..name)
			if bidder and name and bidder == name then
				SNFDEBUG(1,"Found the winner as "..bidder.." for "..data["level"])
				EndAuction(ActiveAuction, name, loot, data["level"])

			end
		end
	elseif itemid then
		_, itemLink = GetItemInfo(itemid);

		SNFDEBUG(3,"CheckLootAgainstBids did not match: "..(itemLink or "")..", "..(itemid or ""))
	end
end

function SNFAddLootBid(cat, sender)

	if not ValidAuction("add new bid") then return end

	local BidList = ActiveAuction["BidList"]
	if BidList then
		if BidList[sender] and BidList[sender]["level"] then
			SNFDEBUG(1,"Overwriting bid: "..BidList[sender]["level"].." with "..cat.." for "..sender)
		end
		BidList[sender] = { ["level"] = cat }
	else
		SNFDEBUG(1,"BidList not initialized!")
	end
	assert(ActiveAuction["BidList"][sender])
	SNF_ClearAuctionChecksum(ActiveRaidName)
end


function SNFDKP_ListActiveBids()

	SNFDEBUG(4, "ListActiveBids()");
	if not ValidAuction("list active bids") then return end

	local BidList = ActiveAuction["BidList"]
	local BidItem = ActiveAuction["AuctionItem"]
	local looter = ActiveAuction["MasterLooter"]

	local init = false


	for bidder, cat in pairs(BidList) do
		if not init then
			SNFDEBUG(0,"Bid Item: "..(BidItem or "nil").." looter: "..(looter or "unknown"))
			init = true
		end
		if not bidder or not cat or not cat["level"] then
			SNFDEBUG(0, "Malformed bid entry: "..(bidder or "Unknown")..":"..((cat and cat["level"]) or ""))
		else
			local raidcount = SNFLoot:GetLootCount(bidder, cat["level"], ActiveRaidName) or ""
			local ttlcount  = SNFLoot:GetLootCount(bidder, cat["level"]) or ""
			SNFDEBUG(0,"Bid List: "..bidder.." bid "..cat["level"].." ttl: "..(ttlcount or "nil")..", this raid: "..(raidcount or "nil"))
--			SNFDEBUG(2, "    This raid:"..(raidcount or "nil").." alltime: "..(ttlcount or "nil"))
		end
	end
	if not init then
		SNFDEBUG(0,"No items on bid list")
	end
end

function SNFDKP_ListHistoricBids(Raid)
	SNFDEBUG(4, "ListHistoricBids("..(Raid or "")..")")

	if Raid then
		if SNFAuctions and SNFAuctions[Raid] then
			SNFDEBUG(0, "Raid: "..Raid)
			ListBidsForRaid(SNFAuctions[Raid])
		end
	else
		for raid, auctionlist in pairs(SNFAuctions) do
			SNFDEBUG(0, "Raid: "..raid)
			ListBidsForRaid(auctionlist)
		end
	end
end

function SNFAddNewAuction(item, looter)

	if not ValidRaid("add new auction") then return end
	SNFDEBUG(1,"Setting Auction item: "..(item or "nil").." looter "..(looter or "nil"))
	NextAuctionNumber()

	ActiveAuctionNumber = LastAuctionNumber
	ActiveAuction = { AuctionItem = item, MasterLooter = looter, BidList = { }}
	ActiveRaid[ActiveAuctionNumber] = ActiveAuction
end

function SNFVerifyAuctionStart(raid, AuctionNumber, item, looter, winner)

	if not (raid and AuctionNumber and item and looter) then
		SNFDEBUG(2, "Bad parameter to SNFVerifyAuctionStart")
		return
	end
	if not SNFAuctions then
		SNFDEBUG(2, "Auction data is not set up! Verify failed");
		return
	end
	if not SNFAuctions[raid] then -- this raid doesn't exist, so we can't sync yet
		SNFDEBUG(2, "Raid "..raid.." does not exist, skipping verify until raid is set up")
		--TODO - make this trigger a request for that raid's setup data
		return
	end
	if SNFAuctions[raid][AuctionNumber] then -- compare the two
		if	SNFAuctions[raid][AuctionNumber]["AuctionItem"] == item and
			SNFAuctions[raid][AuctionNumber]["MasterLooter"] == looter then
			SNFDEBUG(3, "Comparing Auctions.  Local vs Sync - match")
		else
			if SNFAuctions[raid][AuctionNumber]["AuctionItem"] ~= item then
				SNFDEBUG(3, "Comparing Auctions, item is different. ")
			end
			if SNFAuctions[raid][AuctionNumber]["MasterLooter"] ~= looter then
				SNFDEBUG(3, "Comparing Auctions, looter is different. ")
			end
			if SNFAuctions[raid][AuctionNumber]["winner"] ~= winner then
				SNFDEBUG(3, "Comparing Auctions, winner is different. ")
			end
			-- TODO: Decide which copy of data to keep.
		end
	end
	-- TODO: Trigger a compare of individual bids.
end

function SNFInitializeDataAuction(RaidID)
	SNFDEBUG(2, "Raid Initialized Auctions: "..(RaidID or ""))
	ActiveAuction = nil
	ActiveRaidName = RaidID
	if not SNFAuctions[RaidID] then
		SNFAuctions[RaidID] = { }
	end
	ActiveRaid = SNFAuctions[RaidID]
	LastAuctionNumber = GetLastAuctionNum(RaidID)
end

function SNFDeleteRaidAuctions(RaidID)

	if SNFAuctions and RaidID and SNFAuctions[RaidID] then
		SNFAuctions[RaidID] = nil
		SNFDEBUG(0, "Raid Auctions for "..RaidID.." deleted!")
		SNF_ClearAuctionChecksum(RaidID)
	end
end

local function sortLootList(a,b)
	if not (a and b and a["sort1"] and b["sort1"]) then return false end
	if a["sort1"] == b["sort1"] then
		if not (a["sort2"] and b["sort2"]) then return false end
		if a["sort2"] == b["sort2"] then
			if not (a["sort3"] and b["sort3"]) then return false end
			return a["sort3"] < b["sort3"]
		else
			return a["sort2"] < b["sort2"]
		end
	else
		return a["sort1"] < b["sort1"]
	end
end


function SNFDKP_ListLootCouncilSummary()

	SNFDEBUG(4, "ListActiveBids()");
	if not ValidAuction("list active bids") then return end

	local BidList = ActiveAuction["BidList"]
	local BidItem = ActiveAuction["AuctionItem"]
	local looter = ActiveAuction["MasterLooter"]

	local header = nil
	local displist = { }


	for bidder, cat in pairs(BidList) do
		if not header then
			header = "Bid Item: "..(BidItem or "nil").." looter: "..(looter or "nil")
		end
		local new = { }
		if not bidder or not cat or not cat["level"] then
			SNFDEBUG(0, "Malformed bid entry: "..(bidder or "Unknown")..":"..((cat and cat["level"]) or ""))
		else
			--FORMAT OF LIST is name (bidder), bid, data -- where data is probably different per each bid type
			new["name"] = bidder
			new["bid"] = cat["level"]
			new["att"] = SNFAttend:GetRaidsAttended(bidder)
			local x, y = SNFGetPlayerRankAbbreviation(bidder)
			new["rank"] = x
			new["sort1"] = y

			if not x then SNFDEBUG(2, "X IS Nil") end
			if not y then SNFDEBUG(2, "Y IS Nil") end
			if cat["level"] == "UPG" or cat["level"] == "BIS" then
				local upg = SNFLoot:GetLootCount2(bidder, "UPG") or ""
				local bis = SNFLoot:GetLootCount2(bidder, "BIS") or ""
--				SNFOFFICER("Bid: "..bidder.." bids "..cat["level"].." LH: UP-"..upg..", BIS-"..bis..att)
				new["data"] = " LH: UP-"..upg..", BIS-"..bis
				if cat["level"] == "BIS" then new["sort2"] = 1 end
				if cat["level"] == "UPG" then new["sort2"] = 2 end
				new["sort3"] = ((tonumber(upg) or 0) + (tonumber(bis) or 0))
			elseif cat["level"] == "DKP" then
				local spent = (SNFLoot:GetLootCount2(bidder, "DKP") or 0) * 32
				local _, _, earned = SNFAttend:GetRaidsAttended(bidder)

--				SNFOFFICER("Bid: "..bidder.." bids ".."DKP".." spent: "..spent..", Remaining: "..(earned - spent)..att)
				new["data"] = " spent: "..spent..", Remaining: "..(earned - spent)
				new["sort2"] = 0
				new["sort3"] = earned - spent
			else
				local now = SNFLoot:GetLootCount2(bidder, cat["level"], ActiveRaidName) or ""
				local ttl = SNFLoot:GetLootCount2(bidder, cat["level"]) or ""
--				SNFOFFICER("Bid: "..bidder.." bids "..cat["level"].." ever: "..ttl..", this raid: "..now..att)
				new["data"] = " ever: "..ttl..", this raid: "..now
				new["sort2"] = 3
				new["sort3"] = att
			end
			table.insert(displist, new)
		end
	end
	if not header then
		SendChatMessage("No items on bid list", "OFFICER" )
	else
		SendChatMessage(header, "OFFICER" )
	end

	-- Sort list if desired
	if (SNF_CheckSortStatus() == "ON") then
		table.sort(displist, sortLootList)
	end


	-- Display list
	for _, d in ipairs(displist) do
		SendChatMessage(d["rank"].."! "..d["bid"]..": "..d["name"].." "..d["data"].." AT:"..d["att"], "OFFICER" )
	end


end
function SNFDKP_ListLootCouncilSummary2()

	SNFDEBUG(4, "ListActiveBids()");
	if not ValidAuction("list active bids") then return end

	local BidList = ActiveAuction["BidList"]
	local BidItem = ActiveAuction["AuctionItem"]
	local looter = ActiveAuction["MasterLooter"]

	local header = nil
	local displist = { }


	for bidder, cat in pairs(BidList) do
		if not header then
			header = "Bid Item: "..(BidItem or "nil").." looter: "..(looter or "nil")
		end
		local new = { }
		if not bidder or not cat or not cat["level"] then
			SNFDEBUG(0, "Malformed bid entry: "..(bidder or "Unknown")..":"..((cat and cat["level"]) or ""))
		else
			--FORMAT OF LIST is name (bidder), bid, data -- where data is probably different per each bid type
			new["name"] = bidder
			new["bid"] = cat["level"]
			local att, raidcount, nDKP = SNFAttend:GetRaidsAttended(bidder) -- ATT seems to be something that needs to be fixed below WHSTODO
			x, y = SNFGetPlayerRankAbbreviation(bidder)
			new["rank"] = x
			new["sort1"] = y

			if not x then SNFDEBUG(2, "X IS Nil") end
			if not y then SNFDEBUG(2, "Y IS Nil") end
			if cat["level"] == "UPG" or cat["level"] == "BIS" then
				local upg = SNFLoot:GetLootCount2(bidder, "UPG") or 0
				local bis = SNFLoot:GetLootCount2(bidder, "BIS") or 0
--				SNFOFFICER("Bid: "..bidder.." bids "..cat["level"].." LH: UP-"..upg..", BIS-"..bis..att)
				--old: new["data"] = " LH: UP-"..upg..", BIS-"..bis
				new["data"] = " LH: UP+BIS-"..(upg + bis)
				if cat["level"] == "BIS" then new["sort2"] = 1 end
				if cat["level"] == "UPG" then new["sort2"] = 2 end

				SNFDEBUG(0, "ATT ("..(att or "nil")..") is a "..(type(att) or "nil").." upg is a "..(type(upg) or "nil").." bis is a "..(type(bis) or "nil"))
				new["sort3"] = -(tonumber(att or 0)/((tonumber(upg or 0)) + (tonumber(bis or 0))))
				if upg + bis > 0 then
					new["att"] = " ATFactor:"..tonumber(att or 0)/((tonumber(upg) or 0) + (tonumber(bis) or 0))
				else
					new["att"] = " Raids with no loot::"..((tonumber(att or 0) or 0) / 2)
				end
			elseif cat["level"] == "DKP" then
				local spent = (SNFLoot:GetLootCount2(bidder, "DKP") or 0) * 32

--				SNFOFFICER("Bid: "..bidder.." bids ".."DKP".." spent: "..spent..", Remaining: "..(earned - spent)..att)
				new["data"] = " spent: "..spent..", Remaining: "..(nDKP - spent)
				new["sort2"] = 0
				new["sort3"] = nDKP - spent
				new["att"] = " AT:"..(att or "nil").."%"
			else
				local now = SNFLoot:GetLootCount2(bidder, cat["level"], ActiveRaidName) or 0
				local ttl = SNFLoot:GetLootCount2(bidder, cat["level"]) or 0
--				SNFOFFICER("Bid: "..bidder.." bids "..cat["level"].." ever: "..ttl..", this raid: "..now..att)
				new["data"] = " ever: "..ttl..", this raid: "..now
				new["sort2"] = 3
				new["sort3"] = raidcount / ttl
				new["att"] = " AT:"..(att or "nil").."%"
			end
			table.insert(displist, new)
		end
	end
	if not header then
		SendChatMessage("No items on bid list", "OFFICER" )
	else
		SendChatMessage(header, "OFFICER" )
	end

	-- Sort list if desired
	if (SNF_CheckSortStatus() == "ON") then
		table.sort(displist, sortLootList)
	end


	-- Display list
	for _, d in ipairs(displist) do
		SendChatMessage(d["rank"].."! "..d["bid"]..": "..d["name"].." "..d["data"]..d["att"], "OFFICER" )
	end


end

local ATTENDANCE_CUTOFF_FOR_SPECIALS = 75

function SNFDKP_ListLootCouncilSummary3()

	SNFDEBUG(4, "ListActiveBids()");
	if not ValidAuction("list active bids") then return end

	local BidList = ActiveAuction["BidList"]
	local BidItem = ActiveAuction["AuctionItem"]
	local looter = ActiveAuction["MasterLooter"]

	local header = nil
	local displist = { }


	for bidder, cat in pairs(BidList) do
		if not header then
			header = "Bid Item: "..(BidItem or "nil").." looter: "..(looter or "nil")
		end
		local new = { }
		if not bidder or not cat or not cat["level"] then
			SNFDEBUG(0, "Malformed bid entry: "..(bidder or "Unknown")..":"..((cat and cat["level"]) or ""))
		else
			--FORMAT OF LIST is name (bidder), bid, data -- where data is probably different per each bid type
			new["name"] = bidder
			new["bid"] = cat["level"]
			local attended, raidcount, nDKP = SNFAttend:GetRaidsAttended(bidder)
			local attendpct = 0

			if (raidcount > 0) then
				attendpct = tostring(SNFRound(100 * (attended or 0) / raidcount)).."%"
			else
				attendpct = "NaN"
			end

			x, y = SNFGetPlayerRankAbbreviation(bidder)
			if not x then SNFDEBUG(2, "X IS Nil") end
			if not y then SNFDEBUG(2, "Y IS Nil") end
			new["rank"] = x
			new["sort1"] = y

			if cat["level"] == "UPG" or cat["level"] == "BIS" then

				local specials = SNFLoot:CheckForSpecialReport(BidItem, bidder, cat["level"])

				if (specials) then

					new["data"] = " Items of this type: "..specials
					if cat["level"] == "BIS" then new["sort2"] = 1 end
					if cat["level"] == "UPG" then new["sort2"] = 2 end

					if (100 * (attended or 0) / raidcount) < ATTENDANCE_CUTOFF_FOR_SPECIALS then
						SNFDEBUG(1, "Lowering sort on "..bidder.." because they are below the cutoff for attend: "..attendpct)
						new["sort2"] = 3
					end

					new["sort3"] = -specials
					new["att"] = " AT "..attendpct
				else

					local upg = SNFLoot:GetLootCount2(bidder, "UPG") or 0
					local bis = SNFLoot:GetLootCount2(bidder, "BIS") or 0

					new["data"] = " UP+BIS-"..(upg + bis)
					if cat["level"] == "BIS" then new["sort2"] = 1 end
					if cat["level"] == "UPG" then new["sort2"] = 2 end

					SNFDEBUG(1, "ATT ("..(attended or "nil")..") is a "..(type(attended) or "nil").." upg is a "..(type(upg) or "nil").." bis is a "..(type(bis) or "nil"))
					local AFactor = (tonumber(attended or 0)/((tonumber(upg or 0)) + (tonumber(bis or 0))))

					AFactor = SNFRound(AFactor * 10)/ 10
					new["sort3"] = -AFactor
					if upg + bis > 0 then
						new["att"] = " ATFactor:"..AFactor.." AT "..attendpct
					else
						new["att"] = " Raids with no loot::"..(tonumber(attended or 0) / 2).." AT "..attendpct
					end
				end
			elseif cat["level"] == "DKP" then
				--[[ WHS TODO - Does this take off the frozen DKP?  It probably should. ]]--
				local spent = (SNFLoot:GetLootCount2(bidder, "DKP") or 0) * 32

				new["data"] = " spent: "..spent..", Remaining: "..(nDKP - spent)
				new["sort2"] = 0
				new["sort3"] = nDKP - spent
				new["att"] = " AT:"..attendpct
			else
				local now = SNFLoot:GetLootCount2(bidder, cat["level"], ActiveRaidName) or 0
				local ttl = SNFLoot:GetLootCount2(bidder, cat["level"]) or 0
				new["data"] = " ever: "..ttl..", this raid: "..now
				new["sort2"] = 3
				new["sort3"] = attended / ttl
				new["att"] = " AT:"..attendpct
			end
			table.insert(displist, new)
		end
	end
	if not header then
		SendChatMessage("No items on bid list", "OFFICER" )
	else
		SendChatMessage(header, "OFFICER" )
	end

	-- Sort list if desired
	if (SNF_CheckSortStatus() == "ON") then
		table.sort(displist, sortLootList)
	end


	-- Display list
	for _, d in ipairs(displist) do
		SendChatMessage(d["rank"].."! "..d["bid"]..": "..d["name"].." "..d["data"]..d["att"], "OFFICER" )
	end


end

-- raid is the raidid to add the item to
-- i is the specific array index to use - if it is null or doesn't exist as an auction, an element is inserted.
-- winner is the person who got the loot
-- winnerbid is the bid of the person who got the loot
-- looter was the person who handed out the loot - only used for some verification checks
local function  AddAuctionItem(raid, i, winner, winnerbid, item, looter)

	local r = SNFAuctions[raid]

	local a = { }
	if i then -- if i is passed in, try to use it to place the new auction
		if not r[tonumber(i)] then  -- i passed in, but doesn't exist yet - create it
			table.insert(r, tonumber(i), a)
		else
			a = r[tonumber(i)]
		end
	else -- i is not passed in, create a new auction at the end.
		table.insert(r, a)
	end

	a["AuctionItem"] = item --SNFGetDisplayStringFromItemID(itemid)
	a["winner"] = winner
 	a["MasterLooter"] = looter
 	a["winnerbid"] = winnerbid -- this will eventually take the placeo of the nested bid list

	-- but for now, continue to build this so that old versions of the mod still work for people.
	if not a["BidList"] then a["BidList"] = { } end
 	if not a["BidList"][winner] then a["BidList"][winner] = { } end
 	a["BidList"][winner]["level"] = winnerbid
	SNF_ClearAuctionChecksum(raid)
 	return true

end


-- This is called by the synchronization routines.
function SNFSetAuctionSum(raidid, i, item, winner, winnerbid, looter)

	SNFDEBUG(3, "SNFSetAuctionSum()")
	local r = SNFAuctions[raidid]
	if not r then
		SNFDEBUG(0, "Raid "..(raidid or "nil").." doesn't exist, adding raid")
		SNFAuctions[raidid] = { }
		r = SNFAuctions[raidid]
	end
	if r["MasterLooter"] and looter ~= r["MasterLooter"] then
		SNFDEBUG(1, "Raid Looter mismatch, ignoring send of auction data for "..raidid)
		return
	end

	AddAuctionItem(raidid, i, winner, winnerbid, item, looter)
	SNF_ClearAuctionChecksum(raidid)
	return true
end

-- This is called by the manual edit commands
function SNFAddEditItem(raid, winner, bid, item)

	SNFDEBUG(3, "SNFAddEditItem()")
	local r = SNFAuctions[raid]
	if not r then
		SNFDEBUG(0, "Raid "..(raid or "nil").." doesn't exist.")
		SNFDEBUG(0, "Temporary fix -- ADDING RAID")
		SNFAuctions[raid] = { }
		r = SNFAuctions[raid]
	end

	if not (bid == "UPG" or bid == "OFF" or bid == "DKP") then
		SNFDEBUG(0, bid.." not recognized as a valid bid.  Use UPG, OFF, or DKP")
		return true
	end

	if (AddAuctionItem(raid, nil, winner, bid, item, GetUnitName("player"))) then
		SNFDEBUG(0, "Successfully added "..(item or "nil").." as "..(bid or "nil").." bid for "..(winner or "nil").." in raid "..(raid or "nil"))
	else
		SNFDEBUG(0, "Failed to add "..(item or "nil").." as "..(bid or "nil").." bid for "..(winner or "nil").." in raid "..(raid or "nil"))
	end
	SNF_ClearAuctionChecksum(raid)
	return true
end

--[[  SNFAuctions table structure looks like this:

	SNFAuctions - list of raid data tables keyed by a date field, "RaidID".  RaidID looks like '20100303' or CCYYMMDD
	SNFAuctions[RaidID] = { } list of tables, indexed numerically
	SNFAuctions[RaidID][#] =
		"MasterLooter" -- The person that made the "link" chat that triggered the auction to be started
		"winner" -- the individual that eventually received the loot mentioned in the auction
		"AuctionItem" -- the item being auctioned.  Found from the "link" chat trigger
		"BidList" -- list of bids, this list is keyed by the name of the bidder
			[name] = {
				"level" -- value is the bid made by the bidder.
			}
		}

		"checksum" -- very primative checksum used by syncing to determine if updates should be done
	}
]]--
function SNF_ClearAuctionChecksum(raidid)

	if not SNFAuctionChecksums then SNFAuctionChecksums = { } end
	--SNFAuctionChecksums[RaidID] = nil
end

function SNF_GenerateAuctionChecksum(raidid)

	if not SNFAuctionChecksums then SNFAuctionChecksums = { } end

	local checksum = 0

	if (SNFAuctionChecksums[raidid]) then
		checksum = SNFAuctionChecksums[raidid]
	else
		if not SNFAuctions or not SNFAuctions[raidid] then return 0 end

		--first build a list of strings to checksum
		local lst = {  }
		for i, data in ipairs(SNFAuctions[raidid]) do

			local winner = (data["winner"] or "")
			local item = (data["AuctionItem"] or "")
			local winbid = ""
			if data["BidList"] and data["BidList"][winner] and data["BidList"][winner]["level"] then
				winbid = data["BidList"][winner]["level"]
			end
			-- string is a concatenation of the winner, the item, and the winning bid
			table.insert(lst, winner..item..winbid)
		end

		checksum = SNFGenerateFlatListChecksum(lst)
		SNFAuctionChecksums[raidid] = checksum
		SNFDEBUG(3, "Auction checksum ["..(raidid or "nil").."]: "..checksum)
	end
	return checksum
end

function SNF_AuctionChecksumMatch(raidid, check)

	if tonumber(check) == SNF_GenerateAuctionChecksum(raidid) then return true end

	SNFDEBUG(3, "Adv auction chk: ["..(raidid or "nil").."] "..SNF_GenerateAuctionChecksum(raidid).." vs "..(check or "nil"))
	return nil  -- note nil instead of false.
end
